package cliente_admin;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.Enumeration;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

import common.Lector_socket;
import common.Mensaje;
import componentesAux.LectorIpFile;
import control.Control;

public class ClienteAdmin {
	
	private final static int PUERTO_SERVIDOR = 5050;
	private final static String IP_SERVIDOR = "localhost";
	
	private final static String KS_PATH= "keystore/cliente_admin.jks";
	
	private SSLContext ssl_context;
	private SSLSocket socket_cliente;
	

	
	private Lector_socket lector;
	
	private Thread thread_invocante_actual;
	//private AdminMain adminGui;
	private Control adminGui;
	/**
	 * @param args
	 */

	   //public ClienteAdmin(AdminMain admin){
	public ClienteAdmin(Control admin){
		   adminGui = admin;
	   }
	   
	   
	   public boolean verificarPass(char[] pass){
		// load del archivo del keystore
		   	KeyStore key_store;
			try {
				key_store = KeyStore.getInstance("JKS");
				
				//InputStream keystoreStream = getClass().getClassLoader().getResourceAsStream(KS_PATH);
				
				InputStream keystoreStream;
				if(new File("keystore/cliente_admin.jks").isFile()){
					keystoreStream = new FileInputStream("keystore/cliente_admin.jks");
					System.out.println("usando el nuevo");
				}else{
					keystoreStream  = getClass().getClassLoader().getResourceAsStream(KS_PATH);
					System.out.println("usando el viejo");
				}
			        
			   key_store.load(keystoreStream, pass);
			   
			   if(key_store.containsAlias("admin")){
				   char[] passKey = (pass.length<7)? pass: Arrays.copyOfRange(pass, 0, 7);
				   Key key=key_store.getKey("admin", passKey);
				   return key!=null;
					   
			   }
			} catch (Exception e) {
				// TODO Auto-generated catch block
				//e.printStackTrace();
				System.err.println("Password incorrecto");
				return false;
			}
	       
		   
		   return false;
	   }

	   public String iniciar_conexion(char[] pass_ks, char[] pass_keys){
		   String ip_server=(LectorIpFile.existeIniFile())? LectorIpFile.leerIP() : IP_SERVIDOR;
		   try {
			   // load del archivo del keystore
			   	KeyStore key_store = KeyStore.getInstance("JKS");
		        //InputStream keystoreStream = getClass().getClassLoader().getResourceAsStream(KS_PATH);
			   	InputStream keystoreStream;
				if(new File("keystore/cliente_admin.jks").isFile()){
					keystoreStream = new FileInputStream("keystore/cliente_admin.jks");
					System.out.println("usando el nuevo");
				}else{
					keystoreStream  = getClass().getClassLoader().getResourceAsStream(KS_PATH);
					System.out.println("usando el viejo");
				}
		        
		        // inicio del keymanager a partir del keystore
		         key_store.load(keystoreStream, pass_ks);
		         KeyManagerFactory key_manager = KeyManagerFactory.getInstance("SunX509");
		         
		         key_manager.init(key_store, pass_keys);
		         
		         // inicio del trustmanager a partir del keystore
		         TrustManagerFactory trust_store = TrustManagerFactory.getInstance("SunX509");
		         trust_store.init(key_store);
		         
		         // establezco el keystorey truststore utilizado por el socket ssl
		         ssl_context = SSLContext.getInstance("SSL");
		         ssl_context.init(key_manager.getKeyManagers(), trust_store.getTrustManagers(), null);
		         
		         // genero el socket ssl
				 SSLSocketFactory ssl_factory = ssl_context.getSocketFactory();
				 //socket_cliente =(SSLSocket) ssl_factory.createSocket(IP_SERVIDOR, PUERTO_SERVIDOR);
				 socket_cliente =(SSLSocket) ssl_factory.createSocket(ip_server, PUERTO_SERVIDOR);
		         
				 // inicio de handshake
				 socket_cliente.startHandshake();
		         
				 // creo el lector que permite enviar/recibir msjs del protocolo nuestro a trav�s del socket
		         lector = new Lector_socket(socket_cliente);
		         
		         System.out.println("Modulo de control iniciado correctamente");
		         return printSocketInfo(socket_cliente);

		   	}catch (Exception e) {
		   		System.err.println(e.toString());
		   		//e.printStackTrace();
		   		return "No se pudo efectuar la conexi�n: "+e.toString();
		   	}
	   }
	/*   
	@SuppressWarnings("deprecation")
	public Mensaje recibir_msj(){
		   Mensaje msj =lector.leer_msj();
		   
		   if(msj==null){
			   //adminGui.mostrarCierre(); // ????????????????????????????????? SEPT2014
			   cerrar_conexion();
			   thread_invocante_actual.stop();// detengo el thread que lo invoc�
			   System.out.println("se detuvo thread");
			   
			}
		   
		   return msj; 
	   }
	   
	   public void enviar_msj(Mensaje msj){
		   lector.enviar_msj(msj);
	   }
	  */
	   @SuppressWarnings("deprecation")
	public synchronized Mensaje enviarMSJ(Mensaje msj){
		   lector.enviar_msj(msj);
		   Mensaje rta =lector.leer_msj();

		   if(rta==null){
			   adminGui.mostrar_error_conexion();
			   //adminGui.mostrarCierre(); // ????????????????????????????????? SEPT2014
			   cerrar_conexion();
			   
			   thread_invocante_actual.stop();// detengo el thread que lo invoc�
			   
			   System.out.println("se detuvo thread");
			   

		   }

		   return rta; 
	   }
	   public void cerrar_conexion(){
		try {
			lector.cerrar();
			socket_cliente.close();
		} catch (IOException e) {
			System.err.println(e.getMessage());
		}
	   }
	   
	   private String printSocketInfo(SSLSocket s) {
		   	StringBuffer sb = new StringBuffer();
		   	sb.append("Socket class: "+s.getClass()+"\n");
		   	sb.append("\tRemote address = "+s.getInetAddress().toString()+"\n");
		   	sb.append("\tRemote port = "+s.getPort()+"\n");
		   	sb.append("\tLocal socket address = "+s.getLocalSocketAddress().toString()+"\n");
		   	sb.append("\tLocal address = "+s.getLocalAddress().toString()+"\n");
		   	sb.append("\tLocal port = "+s.getLocalPort()+"\n");
		   	sb.append("\tNeed client authentication = "+s.getNeedClientAuth()+"\n");
		      
		   	SSLSession ss = s.getSession();
		   	try {
		   		sb.append("Session class: "+ss.getClass()+"\n");
		        sb.append("\tCipher suite = "+ss.getCipherSuite()+"\n");
		        sb.append("\tProtocol = "+ss.getProtocol()+"\n");
		        sb.append("\tPeerPrincipal = "+ss.getPeerPrincipal().getName()+"\n");
		        sb.append("\tLocalPrincipal = "+ss.getLocalPrincipal().getName()+"\n");
		    }catch (Exception e) {
		   		System.err.println(e.toString());
		   	}
		   	return sb.toString();
	   }

	public Thread getThread_invocante_actual() {
		return thread_invocante_actual;
	}

	public void setThread_invocante_actual(Thread thread_invocante_actual) {
		this.thread_invocante_actual = thread_invocante_actual;
	}
	
	public static void cambiarPassKS(char[] passViejo, char[] passNuevo){
		//Security.addProvider(new BouncyCastleProvider());
		 String dir="keystore";
		 //String path="servidor.jks";
		 String path_nuevo=KS_PATH;
		 try { 
		 InputStream ksStream;
			if(new File(path_nuevo).isFile()){
				System.out.println("LO ENCONTRO");
				ksStream = new FileInputStream(path_nuevo);
			}else{
				System.out.println("NOOOO LO ENCONTRO");
				  ksStream  = ClienteAdmin.class.getClassLoader().getResourceAsStream(KS_PATH);
				  new File(dir).mkdir();
			}
		
			KeyStore ks_viejo = KeyStore.getInstance("JKS");
			ks_viejo.load(ksStream, passViejo);
	        ksStream.close();
			
	        KeyStore ks_nuevo = KeyStore.getInstance("JKS");
	        ks_nuevo.load(null);
	        
	        Enumeration<String> aliases=ks_viejo.aliases();
			while(aliases.hasMoreElements()){
				String alias=aliases.nextElement();
				System.out.println("#"+alias);
				if(ks_viejo.isKeyEntry(alias)){ // si es clave privada
					char[] passKeyViejo= (passViejo.length>6)? Arrays.copyOfRange(passViejo, 0, 7) : passViejo;
					char[] passKeyNuevo= (passNuevo.length>6)? Arrays.copyOfRange(passNuevo, 0, 7) : passNuevo;
					ks_nuevo.setKeyEntry(alias, ks_viejo.getKey(alias, passKeyViejo), passKeyNuevo, new Certificate[]{ks_viejo.getCertificate(alias)});
				}else{// es certificado
					ks_nuevo.setCertificateEntry(alias, ks_viejo.getCertificate(alias));
				}
				
			}
	        
			File ks_file2 = new File(path_nuevo);
			
			FileOutputStream stream2 = new FileOutputStream(ks_file2,false);// false para sobreescribir
			ks_nuevo.store(stream2, passNuevo);
			ksStream.close();
			System.out.println("#se cambio el password del keystore correctamente");
			
		} catch (KeyStoreException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (CertificateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (UnrecoverableKeyException e) {
			e.printStackTrace();
		}
		
	}
	public static boolean verificarPassKS(char[] pass){
		KeyStore ks;
		InputStream ksStream;
		try {
			ks = KeyStore.getInstance("JKS");
			if(new File(KS_PATH).isFile()){
				ksStream = new FileInputStream(KS_PATH); // aca busca por afuera del jar
			}else{
				  ksStream  = ClienteAdmin.class.getClassLoader().getResourceAsStream(KS_PATH); // la diferencia es q aca buscar dentro del jar
			}
			ks.load(ksStream, pass);
	        ksStream.close();
	        return true;
		} catch (KeyStoreException e) {
			System.err.println("No se pudo crear instancia de JKS: "+e.getMessage());
			return false;
		} catch (FileNotFoundException e) {
			System.err.println("No se encontro el archivo con el keystore "+e.getMessage());
			return false;
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} catch (CertificateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} catch (IOException e) {// <<< por acá sale el password incorrecto
			e.printStackTrace();
			return false;
		}
		
		
	}
}
	
	


